﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
using System.ServiceModel;
using System.Linq;
using System.Xml.Linq;

namespace Sinacor.Infra.Tools.ErrorLogCollector.ClientApplication
{
    public partial class ClientMain : Sinacor.Infra.Tools.ErrorLogCollector.BaseMain
    {
        public ClientMain()
        {
            InitializeComponent();
            this.Text += " - Cliente";
        }

        protected override void Collect(DateTime from, DateTime to, string path)
        {
            bool clientEmpty = true;
            bool serverEmpty = true;
            bool serverError = false;
            Exception serverException = null;
            LogPackage clientPackage = null;
            LogPackage serverPackage = null;
            XmlSerializer serializer = new XmlSerializer(typeof(LogPackage));


            this.ShowStatus("Coletando informações do cliente...");

            // Coletar log cliente
            ClientCollector clientCollector = new ClientCollector();
            clientPackage = clientCollector.Collect(from, to);

            if (clientPackage.Client.Logs.Count > 0)
                clientEmpty = false;

            this.ShowStatus("Coletando informações do servidor...");

            try
            {
                // Coletar log server
                serverPackage = DownloadServerLogPackage(from, to);

                if (serverPackage.Server.Logs != null && serverPackage.Server.Logs.Count > 0)
                    serverEmpty = false;
            }
            catch (Exception ex)
            {
                serverError = true;
                serverException = ex;
            }

            this.ShowStatus("Gerando pacote...");

            // Merge do client e do server
            if (!serverError)
            {
                clientPackage.Server = new Package<ServerEnvironmentData>();

                clientPackage.Server.Environment = serverPackage.Server.Environment;
                if (!serverEmpty)
                    clientPackage.Server.Logs.AddRange(serverPackage.Server.Logs);
            }


            // Salvar e zipar package
            if (!clientEmpty || !serverEmpty)
            {
                if (File.Exists(path))
                    File.Delete(path);

                using (MemoryStream stream = new MemoryStream())
                {
                    serializer.Serialize(stream, clientPackage);

                    stream.Position = 0;

                    using (Ionic.Zip.ZipFile zipFile = new Ionic.Zip.ZipFile(path))
                    {
                        zipFile.AddEntry("LogPackage.xml", "\\", stream);
                        zipFile.Save();
                    }
                }
            }

            this.ShowStatus(string.Empty);

            if (!clientEmpty && !serverEmpty && !serverError)
                MessageBox.Show("Logs do cliente e do servidor coletados com sucesso", "Informação", MessageBoxButtons.OK, MessageBoxIcon.Information);

            else if (!clientEmpty && serverEmpty && !serverError)
                MessageBox.Show("Logs do cliente coletados com sucesso, nenhum log encontrado no servidor para o período informado", "Informação", MessageBoxButtons.OK, MessageBoxIcon.Information);

            else if (clientEmpty && !serverEmpty && !serverError)
                MessageBox.Show("Logs do servidor coletados com sucesso, nenhum log encontrado no cliente para o período informado", "Informação", MessageBoxButtons.OK, MessageBoxIcon.Information);

            else if (clientEmpty && serverEmpty && !serverError)
                MessageBox.Show("Nenhum log encontrado no cliente e no servidor para o período informado", "Informação", MessageBoxButtons.OK, MessageBoxIcon.Information);

            else if (!clientEmpty && serverError)
                MessageBox.Show("Logs do cliente coletados com sucesso. Não foi possível coletar os logs do servidor, utilize o utilitário disponível no servidor para realizar a coleta.\n\n" + serverException.ToString(), "Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning);

            else if (clientEmpty && serverError)
                MessageBox.Show("Nenhum log encontrado no cliente para o período informado. Não foi possível coletar os logs do servidor, utilize o utilitário disponível no servidor para realizar a coleta.\n\n" + serverException.ToString(), "Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }

        public LogPackage DownloadServerLogPackage(DateTime from, DateTime to)
        {
            LogPackage package = null;

            XDocument config = XDocument.Load(Path.GetFullPath(Application.StartupPath + @"..\..\..\UI\Application\Infra\Infra.Authorization.config"));

            string address = (from c in config.Descendants()
                              where c.Name == "endpoint" &&
                                   c.Attribute("name").Value == "Tcp.Infra.Authorization.User.IUser"
                              select c.Attribute("address").Value).FirstOrDefault();

            address += @"/stream";

            NetTcpBinding binding = new NetTcpBinding();
            binding.Security.Mode = SecurityMode.None;
            binding.TransferMode = TransferMode.Streamed;
            binding.SendTimeout = new TimeSpan(0, 30, 0);
            binding.OpenTimeout = new TimeSpan(0, 30, 0);
            binding.CloseTimeout = new TimeSpan(0, 30, 0);
            binding.ReceiveTimeout = new TimeSpan(0, 30, 0);
            binding.MaxReceivedMessageSize = Int32.MaxValue;
            binding.MaxBufferSize = Int32.MaxValue;

            using (ChannelFactory<IUser> updatesDownloadService = new ChannelFactory<IUser>(binding, address))
            {
                IUser client = updatesDownloadService.CreateChannel();

                using (Stream packageFile = client.DownloadLogPackage(from, to))
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(LogPackage));

                    package = (LogPackage)serializer.Deserialize(packageFile);
                }
            }

            return package;
        }
    }
}
